home *** CD-ROM | disk | FTP | other *** search
- /* disk.c - MS-DOS diskette service for Tar program (see file tar.c)
- * Author: T.V.Shaporev
- * Prepared for release 19 Oct 1990
- *
- * Called by readtape(), writetape() etc. - see file tape.c
- */
- #include "sysup.h"
- #ifdef __TURBOC__
-
- #include <string.h>
- #include <stdio.h>
-
- #include "modern.h"
- #include "define.h"
-
- extern int diskserv __ARGS__((int, int, int, int, int, int, void far *));
- extern void printbs __ARGS__(( int ));
-
- static void errdisk __ARGS__(( int ));
- static void redrive __ARGS__(( void ));
- static int trydisk __ARGS__(( int, char *, int ));
- static void nextdisk __ARGS__(( void ));
- static void skipsect __ARGS__(( void ));
- static void ibmdisk __ARGS__(( int, char *, int ));
- static void rainbow __ARGS__(( int, char *, int ));
-
- #define FDC_STATUS (*(char far *)0x0490L)
-
- static unsigned short heads, tracks, sectors, last_seg, this_seg;
- static char calibr = 0;
-
- struct { char *type_disk; unsigned size, heads, tracks, sectors; }
- ftab[] = { {"fd048ss8", 160, 1, 40, 8 },
- {"fd048ss9", 180, 1, 40, 9 },
- {"fd048ds8", 320, 2, 40, 8 },
- {"fd048ds9", 360, 2, 40, 9 },
- {"fd135ds9", 720, 2, 80, 9 },
- {"fd096ds9", 720, 2, 80, 9 },
- {"fd096ds15", 1200, 2, 80, 15 },
- {"fd135ds18", 1440, 2, 80, 18 } };
-
- static void errdisk(n)
- int n;
- {
- register int i;
- static struct { unsigned char code; char *text; } errtab[] = {
- { 0, "undefined error" },
- { 0x00, "no error on last operation" },
- { 0x01, "invalid request to controller" },
- { 0x02, "bad address mark" },
- { 0x03, "write protect" },
- { 0x04, "sector ID bad or not found" },
- { 0x05, "reset failed" },
- { 0x06, "floppy changed line on" },
- { 0x08, "DMA failure" },
- { 0x09, "DMA overrun: attempted to write across 64K" },
- { 0x0b, "bad track flag encountered" },
- { 0x0C, "media type not found" },
- { 0x10, "bad CRC: invalid CRC when data checked" },
- { 0x11, "recoverable error found; data corrected" },
- { 0x20, "controller failure" },
- { 0x40, "bad seek; requested track not found" },
- { 0x80, "time out; drive did not respond" },
- { 0xff, "sense operation failed" } };
-
- for (i=1; errtab[i].code!=n && i<dimof(errtab); i++) ;
- if (i>=dimof(errtab)) i = 0;
- fprintf(myout, "Tar: diskette error: %s\n", errtab[i].text);
- }
-
- int argdisk(k)
- register k;
- {
- register i;
-
- for (i=0; ftab[i].size!=k && i<dimof(ftab); i++) ;
- if (i >= dimof(ftab)) return -1;
- sectors = ftab[i].sectors;
- tracks = ftab[i].tracks;
- heads = ftab[i].heads;
- return 0;
- }
-
- int defdev(k)
- register char *k;
- {
- register i;
-
- for (i=0; stricmp(ftab[i].type_disk, k)!=0 && i<dimof(ftab); i++) ;
- if (i < dimof(ftab)) {
- sectors = ftab[i].sectors;
- tracks = ftab[i].tracks;
- heads = ftab[i].heads;
- } else if (stricmp("rainbow", k) == 0) {
- calibr = RAINBOW;
- sectors = 10;
- tracks = 80;
- heads = 1;
- } else {
- return -1;
- }
- return 0;
- }
-
- static void redrive() /* reset & recalibrate drive */
- {
- (void)diskserv(0, ndrive, 0, 0, 1, 1, NULL);
- if (calibr & QUADISK) {/* Init 800 */
- FDC_STATUS = 0x61; /* FDC status buts <- 61h - ??? */
- /* verify Track 0 Sector 1 Side 0 */
- (void)diskserv(4, ndrive, 0, 0, 1, 1, NULL);
- /* verify Track 1 Sector 1 Side 0 */
- (void)diskserv(4, ndrive, 0, 1, 1, 1, NULL);
- (void)diskserv(0, ndrive, 0, 0, 1, 1, NULL);
- FDC_STATUS = 0x54; /* FDC status buts <- 54h - ??? */
- } else if (calibr != 0) {
- (void)diskserv(0x17, ndrive, 0, 0, 1, calibr, NULL);
- }
- }
-
- void inidisk(void)
- {
- register k;
- unsigned tb;
- struct {
- short int ndisks, maxhead, maxtrack, maxsect;
- } dp;
-
- if (!calibr) {
- /* reset drive */
- (void)diskserv(0, ndrive, 0, 0, 1, 1, NULL);
- /* get drive params (set default to 2x40x9) */
- (void)diskserv(8, ndrive, 1, 39, 9, 9, &dp);
-
- if ((tb = ++(dp.maxhead) * ++(dp.maxtrack) * dp.maxsect) == 0) {
- fprintf(stderr, "Tar: drive not present\n");
- done(ERINIT);
- }
- if (!k_flag) {
- sectors = dp.maxsect; tracks = dp.maxtrack; heads = dp.maxhead;
- if (v_flag) fprintf(myout, "Diskette capacity %uK assigned\n",
- tb / (1024/BLKSIZE) );
- }
- last_seg = sectors*tracks*heads;
- if (last_seg == 2880) {
- calibr = tb == 2880 ? 3 : 0;
- } else if (last_seg == 2400) {
- calibr = tb == 2400 ? 3 : 0;
- } else if (last_seg == 1440) {
- calibr = tb == 2880 ? 2 :
- tb == 2400 ? QUADISK :
- tb == 1440 ? 4 : 0;
- } else if (last_seg == 720) {
- calibr = tb == 2400 ? 2 : tb == 720 ? 1 : 0;
- } else if (last_seg == 640) {
- calibr = tb == 2400 ? 2 : tb == 720 || tb == 640 ? 1 : 0;
- } else if (last_seg == 360) {
- calibr = tb == 2400 ? 2 : tb == 720 || tb == 360 ? 1 : 0;
- } else if (last_seg == 320) {
- calibr = tb == 2400 ? 2 : tb == 720 || tb == 360 ||
- tb == 640 || tb == 320 ? 1 : 0;
- }
- }
- this_seg = 0;
-
- redrive();
-
- /* get drive error status */
- k = diskserv(1, ndrive, 0, 0, 1, 1, NULL);
- if (k!=0 && k!=6) {
- errdisk(k);
- if (k!=0x11) done(ERINIT);
- }
- if (!cblock) {
- /* Some BIOSes do strange things on quad drives. */
- /* I guess they loose info while read or write through 9th to */
- /* 10th sector. I hope, the following solves the problem. */
- printbs(cblock = a_flag ? 1 : (sectors < 9 ? sectors : 3));
- }
- }
-
- static int trydisk(wr, buf, bl)
- int wr, bl;
- char *buf;
- {
- int i, k;
- register short s, h, t;
-
- s = this_seg % sectors + 1; /* sector */
- t = this_seg / sectors;
- h = t % heads; /* head */
- t /= heads; /* track */
-
- i = 0;
- do {
- k = diskserv((wr ? 3 : 2), ndrive, h, t, s, bl, buf);
- #if 0
- if (!k && wr) {/* verify */
- char chk[NBLOCK*BLKSIZE];
- k = diskserv(4, ndrive, h, t, s, bl, buf);
- }
- #endif
- if (k) redrive();
- } while (k && ++i<3);
-
- if (cbreak) done(0);
-
- if (k == 0 || k == 0x11) {
- k = 0;
- } else if (k!=0x02 && k!=0x04 && k!=0x0B && k!=0x10 && k!=0x40) {
- errdisk(k); /* fatal error */
- if (!i_flag || wr) done(wr ? EWRITE : ERREAD);
- }
- return k;
- }
-
- static void nextdisk()
- {
- fprintf(stderr, "Tar: insert NEXT diskette and press ENTER when ready...");
- (void)yes_no('\0');
- this_seg = 0;
- redrive();
- }
-
- static void skipsect()
- {
- fprintf(myout, "Tar: warning: bad sector %d, skipped\n", this_seg);
- }
-
- static void ibmdisk(wr, buf, bl)
- int wr, bl;
- char *buf;
- {
- int i, j, k;
-
- i = sectors - this_seg % sectors;
- if (i > bl) i = bl;
- while (bl > 0) {
- if (this_seg >= last_seg) nextdisk();
- if ((k = trydisk(wr, buf, i)) == 0) {
- this_seg += i;
- buf += i*BLKSIZE;
- bl -= i;
- } else {
- for (j=0; j<i; j++) {
- if (i>1) k = trydisk(wr, buf, 1);
- if (k == 0) { /* one sector o'k */
- buf += BLKSIZE;
- --bl;
- } else skipsect();
- ++this_seg;
- }
- }
- i = sectors < bl ? sectors : bl;
- }
- }
-
- static void rainbow(wr, buf, bl)
- int wr, bl;
- char *buf;
- {
- int i, j, k, n;
- static char e85tab[50] = {
- /* x = 0 1 2 3 4 5 6 7 8 9 */
- /* 0x */ 1, 3, 5, 7, 9, 2, 4, 6, 8, 10,
- /* 1x */ 3, 5, 7, 9, 1, 4, 6, 8, 10, 2,
- /* 2x */ 5, 7, 9, 1, 3, 6, 8, 10, 2, 4,
- /* 3x */ 7, 9, 1, 3, 5, 8, 10, 2, 4, 6,
- /* 4x */ 9, 1, 3, 5, 7, 10, 2, 4, 6, 8,
- };
-
- while (bl > 0) {
- if (this_seg >= last_seg) nextdisk();
-
- i = (this_seg/10 + 1) % 80; /* track */
- j = e85tab[this_seg%50]; /* sector */
- n = 0;
- do {
- k = diskserv((wr?3:2), ndrive, 0, i, j, 1, buf);
- if (k && ++n<3) redrive();
- } while (k && n<3);
-
- if (cbreak) done(0); /* ??? */
-
- if (!k) { buf += BLKSIZE; --bl; } else skipsect();
- ++this_seg;
- }
- }
-
- /* Interface routines */
- int dread(buf, n)
- char *buf; register n;
- {
- register k = n / BLKSIZE;
- if (n % BLKSIZE) return -1;
- if (calibr == RAINBOW) rainbow(0, buf, k); else ibmdisk(0, buf, k);
- return n;
- }
-
- int dwrite(buf, n)
- char *buf; register n;
- {
- n = (BLKSIZE-1 + n) / BLKSIZE;
- if (calibr == RAINBOW) rainbow(1, buf, n); else ibmdisk(1, buf, n);
- return BLKSIZE*n;
- }
-
- int dback(n)
- register n;
- {
- this_seg = this_seg > n ? this_seg-n : 0;
- return n;
- }
- #endif